package com.rt.gptnext.common.utils.http;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.rt.gptnext.common.utils.json.JsonUtil;
import lombok.Data;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 三方HTTP信息
 *
 * @author gaoyiyang
 **/
@Data
public class HttpInfo {

    /**
     * 请求分组
     */
    private String group = "default";

    /**
     * 接口名称
     */
    private String apiName = StrUtil.EMPTY;

    /**
     * 业务ID
     */
    private Serializable businessId;

    /**
     * 状态码
     */
    private int statusCode;

    /**
     * 请求耗时
     */
    private long time;

    /**
     * 开始时间
     */
    private long startTime;

    /**
     * 结束时间
     */
    private long endTime;

    /**
     * 原始地址
     */
    private String originUrl;

    /**
     * 实际请求地址
     */
    private String url;

    /**
     * 请求体
     */
    private String requestBody;

    /**
     * 请求头
     */
    private Map<String, List<String>> requestHeaders;

    /**
     * 响应头
     */
    private Map<String, List<String>> responseHeaders;

    /**
     * 错误信息
     */
    private Throwable error;

    /**
     * 响应体
     */
    private byte[] responseBody = new byte[0];

    /**
     * 请求方法
     */
    private String method;

    /**
     * 是否下载请求
     */
    private boolean isDownload;

    /**
     * 是否请求成功
     */
    private boolean success;

    public static String headers2Str(Map<String, List<String>> headers) {
        StringBuilder sb = new StringBuilder();
        if (headers == null || headers.isEmpty()) {
            return StrUtil.EMPTY;
        }
        headers.forEach((name, values) -> sb.append(name)
                .append(":")
                .append("[")
                .append(CollUtil.join(values, StrUtil.COMMA))
                .append("];"));
        return sb.toString();
    }

    public void setRequestBody(String requestBody) {
        if (StrUtil.length(requestBody) > 4000 && JSONUtil.isTypeJSON(requestBody)) {
            this.requestBody = JsonUtil.toSafeJsonString(requestBody);
        } else {
            this.requestBody = requestBody;
        }
    }

    /**
     * 返回日志
     *
     * @param logLevel    日志等级
     * @param maxResponse 最大响应长度
     * @return 日志信息
     */
    public String toLog(HttpLogLevel logLevel, int maxResponse) {
        if (logLevel == null) {
            return null;
        }
        List<String> logs = new ArrayList<>();
        logs.add("\n\n================请求开始================");
        logs.add(StrUtil.format("[request]group     ----->:{}", group));
        logs.add(StrUtil.format("[request]apiName   ----->:{}", apiName));
        logs.add(StrUtil.format("[request]businessId----->:{}", businessId));
        logs.add(StrUtil.format("[request]start-time----->:{}", DateUtil.formatDateTime(new Date(startTime))));
        logs.add(StrUtil.format("[request]    method----->:{}", method));
        logs.add(StrUtil.format("[request]origin-url----->:{}", originUrl));
        logs.add(StrUtil.format("[request]       url----->:{}", url));
        logs.add(StrUtil.format("[request]    header----->:{}", headers2Str(requestHeaders)));
        if (requestBody != null) {
            logs.add(StrUtil.format("[request]      body----->:{}", requestBody));
        }
        logs.add(StrUtil.format("[response]status-code<-----:{}", statusCode));
        logs.add(StrUtil.format("[response]   validate<-----:{}", success));
        logs.add(StrUtil.format("[response]     header<-----:{}", headers2Str(responseHeaders)));
        if (error != null) {
            logs.add(StrUtil.format("[response]      error<-----:{}", error.getMessage()));
        } else if (logLevel == HttpLogLevel.BODY) {
            String inputBody;
            if (isDownload) {
                inputBody = "[file(len:" + responseBody.length + ")]";
            } else {
                inputBody = new String(responseBody);
                if (StrUtil.length(inputBody) > maxResponse) {
                    if (JSONUtil.isTypeJSON(inputBody)) {
                        inputBody = JsonUtil.toSafeJsonString(inputBody);
                    } else {
                        inputBody = StrUtil.sub(inputBody, 0, maxResponse) + "...[len:" + StrUtil.length(inputBody) + "]";
                    }
                }
            }
            logs.add(StrUtil.format("[response]       body<-----:{}", inputBody));
        }
        logs.add(StrUtil.format("[response]   end-time<-----:{}", DateUtil.formatDateTime(new Date(endTime))));
        logs.add(StrUtil.format("================请求结束[耗时:{}ms]================\n\n", time));

        return CollUtil.join(logs, "\n");
    }

}
